import _ from 'lodash'

export class EventEmitter {
  constructor(exactMatch) {
    this.events = []
    this.matchFn = exactMatch ? _.eq : _.startsWith
  }

  on(event, listener) {
    if (!listener) {
      console.warn(`WARN: registering empty listener for event "${event}"`)
      return
    }

    let el = _.find(this.events, e => e.event === event)

    if (el) {
      el.listeners.push(listener)
    } else {
      this.events.push({ event, listeners: [listener] })
    }

    return () => this.removeListener(event, listener)
  }

  removeListener(event, listener) {
    let elIdx = _.findIndex(this.events, e => e.event === event)
    if (elIdx === -1) {
      return
    }

    const lIdx = _.indexOf(this.events[elIdx].listeners, listener)
    if (lIdx > -1) {
      this.events[elIdx].listeners.splice(lIdx, 1)
    }

    if (this.events[elIdx].listeners.length === 0) {
      this.events.splice(elIdx, 1)
    }
  }

  emit(event, ...args) {
    for (let i = 0; i < this.events.length; i++) {
      const el = this.events[i]
      if (this.matchFn(event, el.event)) {
        for (let j = 0; j < el.listeners.length; j++) {
          try {
            el.listeners[j].apply(this, args)
          } catch (e) {
            // 丢掉错误
          }
        }
      }
    }
  }

  once(event, listener) {
    const removeFn = this.on(event, (...args) => {
      removeFn()
      try {
        listener.apply(this, args)
      } catch (e) {
        // 丢掉错误
      }
    })
  }
}
